package com.sq.partner.manager.service.impl;

import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.annotation.Resource;

import org.apache.log4j.Logger;
import org.dom4j.Document;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import org.dom4j.Node;
import org.springframework.stereotype.Service;

import com.sq.partner.manager.common.Config;
import com.sq.partner.manager.common.Constants;
import com.sq.partner.manager.common.GatewayCache;
import com.sq.partner.manager.common.Result;
import com.sq.partner.manager.common.exception.AppException;
import com.sq.partner.manager.dao.CardInfoDao;
import com.sq.partner.manager.dao.CommamtFeeDao;
import com.sq.partner.manager.dao.FacadeAppFormDao;
import com.sq.partner.manager.dao.FacadeNewPaymentDao;
import com.sq.partner.manager.dao.FacadePaymentDao;
import com.sq.partner.manager.dao.FacadeTempPolicyDao;
import com.sq.partner.manager.dao.OutboundCardApplyDao;
import com.sq.partner.manager.mybatis.model.CardInfo;
import com.sq.partner.manager.mybatis.model.FacadeAppForm;
import com.sq.partner.manager.mybatis.model.FacadeNewPayment;
import com.sq.partner.manager.mybatis.model.FacadePayment;
import com.sq.partner.manager.mybatis.model.FacadeTempPolicy;
import com.sq.partner.manager.mybatis.model.FacadeTransLog;
import com.sq.partner.manager.service.FacadeAppFormService;
import com.sq.partner.manager.service.FacadeTempPolicyService;
import com.sq.partner.manager.service.OutboundCardApplyService;
import com.sq.partner.manager.service.PayService;
import com.sq.partner.manager.util.DateUtil;
import com.sq.partner.manager.util.DecimalUtil;
import com.sq.partner.manager.util.FreeMarkerUtil;
import com.sq.partner.manager.util.HttpConnectorNewpayUtil;
import com.sq.partner.manager.util.HttpConnectorUtil;
import com.sq.partner.manager.util.LogUtil;
import com.sq.partner.manager.util.MD5Util;
import com.sq.partner.manager.util.StrUtil;
import com.sq.partner.manager.webservice.PaymentClient;

@Service
public class PayServiceImpl implements PayService {
    private static Logger logger = LogUtil.getLog(PayServiceImpl.class);

    @Resource
    private FacadePaymentDao facadePayDao;
    @Resource
    private FacadeAppFormDao facadeAppFormDao;
    @Resource
    private FacadeTempPolicyDao facadeTempPolicyDao;
    @Resource
    private FacadeAppFormService facadeAppFormService;
    @Resource
    private FacadeTempPolicyService facadeTempPolicyService;
    @Resource
    private CardInfoDao cardInfoDao;
    @Resource
    private OutboundCardApplyService outboundCardApplyService;

    @Resource
    private CommamtFeeDao commamtFeeDao;
    @Resource
    private OutboundCardApplyDao outboundCardApplyDao;
    
    @Resource
    private FacadeNewPaymentDao facadeNewPaymentDao; //对接新支付平台
    

    /**
     * 投保单号查询最大交易流水号，存在则+1，不存在则初始化为0001 交易流水号生成规则 投保单号+TXS+四位序列
     * 
     * @param appno
     *            投保单号
     * @param transCode
     *            交易代码
     * @return
     * @throws Exception
     */
    @Override
    public String generateTradingSerialNumber(String appno) throws Exception {
        String code = facadePayDao.findFacadeTransLogByTransNo(appno);
        if (StrUtil.isEmpty(code)) {
            code = "0001";
        }
        return appno + "TXS" + code;
    }

    @Override
    public FacadeTempPolicy findPayFacadeTempPolicy(String stagNo)
            throws Exception {
        // 只处理
        FacadeTempPolicy facadeTempPolicy = new FacadeTempPolicy();
        facadeTempPolicy.setStagNo(stagNo);
        facadeTempPolicy.setStatus("02,11,12,13,14");
        facadeTempPolicy = facadeTempPolicyDao
                .selectFacadeTempPolicy(facadeTempPolicy);

        FacadeAppForm facadeAppForm = new FacadeAppForm();
        facadeAppForm.setStagNo(stagNo);
        facadeAppForm.setStatus("02,11,12,13,14");
        List<FacadeAppForm> facadeAppForms = facadeAppFormDao
                .selectFacadeAppFormListPayByNlife(facadeAppForm);
        if (facadeAppForms.size() == 0) {
            logger.info("暂存单号：" + stagNo + "没有投保信息");
            throw new Exception();
        }
        facadeTempPolicy.setFacadeAppForms(facadeAppForms);

        return facadeTempPolicy;
    }

    /**
     * 根据投保单号再次发起缴费确
     * 
     * @param cardNo
     * @param appNo
     * @param stagNo
     * @return
     * @throws Exception
     */
    @Override
    public Result paymentConfirmAgain(String cardNo, String appNo, String stagNo)
            throws Exception {
        FacadeTempPolicy facadeTempPolicy = facadeTempPolicyDao
                .queryFacadeTempPolicyById(stagNo);
        String templates = Constants.NLIFE_T03_TEMPLATES;
        String transCode = Constants.GW_CH_TX_T03;
        String trialUrl = Constants.NLIFE_TRIAL_URL;
        String resultCodeSuccess = Constants.NLIFE_STATUS_CODE;
        String resultCodeRepeat = "02";

        try {
            Map<String, Object> map = new HashMap<String, Object>();
            map.put("appNo", appNo);
            map.put("status", "'" + Constants.POL_STATUS_14 + "','"
                    + Constants.POL_STATUS_12 + "','"
                    + Constants.POL_STATUS_02 + "'");
            Map<String, Object> messageMap = facadePayDao
                    .queryConfirmAgainMessage(map);
            Map<String, String> xmlMap = new HashMap<String, String>();
            FacadeTransLog translog;

            FacadePayment facadepayment = getFacadePaymentByPayId(facadeTempPolicy
                    .getStagNo());
            FacadeAppForm appForm = facadeAppFormDao
                    .queryFacadeAppFormByAppNo(appNo);

            if (messageMap != null) {
                if (Constants.POL_STATUS_02.equals(messageMap.get("STATUS"))) {
                    return Result.success("您已出单成功");
                }
                String fkChannelCode = messageMap.get("FK_CHANNEL_CODE") != null ? messageMap
                        .get("FK_CHANNEL_CODE").toString() : "";
                String subChannelCode = messageMap.get("PARTNE_SALE_NO") != null ? messageMap
                        .get("PARTNE_SALE_NO").toString() : "";
                xmlMap.put("TRANSRDATE",
                        DateUtil.format(new Date(), "yyyy-MM-dd HH:mm:ss"));
                logger.info("投保单号:" + appNo + "开发发送缴费确认请求");
                xmlMap.put(
                        "APPNO",
                        messageMap.get("TRAD_APP_NO") != null ? messageMap.get(
                                "TRAD_APP_NO").toString() : "");
                xmlMap.put("PRODUCTCODE",
                        messageMap.get("INSU_PLAN_NO") != null ? messageMap
                                .get("INSU_PLAN_NO").toString() : "");
                xmlMap.put("PARTNERCODE", fkChannelCode);
                xmlMap.put("PARTNERSUBCODE", subChannelCode);
                String payMode = getPayMode(
                        facadepayment.getPaymentType());
                xmlMap.put("PAY_MODE", payMode);

                xmlMap.put(
                        "TRANSRN_NO",
                        messageMap.get("PAY_NO") != null ? messageMap
                                .get("PAY_NO") + "" : "");
                xmlMap.put(
                        "TH_MERCHANT",
                        messageMap.get("MER_ID") != null ? messageMap
                                .get("MER_ID") + "" : "");
                xmlMap.put("PAY_NO", "");
                xmlMap.put("PAY_NAME", "");
                xmlMap.put("PAY_BUSINESS", "");

                // 根据投保单号生成交易流水号
                String serialnnumber = generateTradingSerialNumber(appNo);
                xmlMap.put("SERIALNUMBER", serialnnumber);

                xmlMap.put("ENDORSEAPPNO", "");// 批改列为空
                xmlMap.put("BUSITYPE", "T");
                FacadePayment payment = getFacadePaymentByPayId(stagNo);
                java.text.DecimalFormat myformat = new java.text.DecimalFormat(
                        "0.00");
                //激活卡一条缴费信息可能对应多条投保信息，金额是所有投保单金额总和
                String payfee = myformat
                      .format(appForm.getTotPremamt() == null ? "" : appForm.getTotPremamt());
                xmlMap.put("PAYFEE", payfee);
                xmlMap.put("PAYDATE", DateUtil.format(payment.getPayDate(),
                        "yyyy-MM-dd HH:mm:ss"));
                xmlMap.put("CUSTOMERNO", payment.getMerId());
                // 卡号
                xmlMap.put("CARDNO", cardNo);
                String xml = FreeMarkerUtil.process(Config.getProp(templates),
                        xmlMap);
                logger.info("投保单号:" + appNo + "生成FreeMarker为:" + xml);
                // 缴费发送前插入交易记录表信息
                translog = new FacadeTransLog();
                translog.setTransNo(serialnnumber);
                translog.setTransCode(transCode);
                translog.setStagNo(stagNo);
                translog.setAppNo(appNo);
                translog.setRequestXml(xml);
                translog.setRequestDate(new Date());
                facadePayDao.insertFacadeTransLog(translog);
                String responseXml = HttpConnectorUtil
                        .interaction(Config.getProp(trialUrl), xml,
                                fkChannelCode, transCode);
                if (StrUtil.isNotEmpty(responseXml)) {// 这里是连接成功
                    logger.info(responseXml);
                    Document document = DocumentHelper.parseText(responseXml);
                    Element root = document.getRootElement();
                    String resultCode = root.selectSingleNode(
                            "/INSUREQRET/HEAD/RESULTCODE").getText();
                    String errinfo = root.selectSingleNode(
                            "/INSUREQRET/HEAD/ERRINFO").getText();
                    String polNo = root
                            .selectSingleNode("/INSUREQRET/MAIN/POLNO") != null ? root
                            .selectSingleNode("/INSUREQRET/MAIN/POLNO")
                            .getText() : "";
                    String eUrl = root
                            .selectSingleNode("/INSUREQRET/MAIN/EURL") != null ? root
                            .selectSingleNode("/INSUREQRET/MAIN/EURL")
                            .getText() : "";
                    // 缴费接受后更新交易记录表信息
                    translog = new FacadeTransLog();
                    translog.setTransNo(serialnnumber);
                    translog.setResponseXml(responseXml);
                    translog.setResponseDate(new Date());
                    translog.setResultCode(resultCode);
                    translog.setResultDesc(errinfo);
                    try {
                        facadePayDao.updateFacadeTransLog(translog);
                    } catch (Exception e) {
                        logger.info("记录日志：", e);
                    }
                    // 00缴费确认成功,02缴费重复投保
                    if (resultCodeSuccess.equals(resultCode)
                            || resultCodeRepeat.equals(resultCode)) {
                        map = new HashMap<String, Object>();
                        map.put("appNo", appNo);
                        map.put("status", Constants.POL_STATUS_02);
                        map.put("polNo", polNo);
                        map.put("polSubDate", new Date());
                        map.put("updateTime", new Date());
                        if (StrUtil.isNotEmpty(eUrl)) {
                            map.put("eUrl", eUrl);
                        }
                        facadePayDao.updateFacadeAppFormByAppno(map);

                        // 卡单表状态更新为已激活
                        CardInfo cardInfo = new CardInfo();
                        cardInfo.setCardNo(cardNo);
                        cardInfo.setStatus(Constants.ACTIR_CARD_ACTIVABLE);
                        //激活时间
                        cardInfo.setAppDate(DateUtil.getNowDate(
                                "yyyy-MM-dd HH:mm:ss"));
                        //起保时间
                        cardInfo.setEffDate(DateUtil.parse(appForm.getStringEffDate(),
                                "yyyy-MM-dd HH:mm:ss"));
                        cardInfoDao.updateCardStatus(cardInfo);
                        // 确认该保单号是否为最后一个缴费确认，如果是则修改暂存单表
                        map = new HashMap<String, Object>();
                        map.put("stagNo", stagNo);
                        map.put("status", Constants.POL_STATUS_02);
                        List<String> isExist = facadePayDao
                                .queryConfirmToLast(map);
                        if (isExist == null || isExist.size() == 0) {
                            map = new HashMap<String, Object>();
                            map.put("payId", stagNo);
                            map.put("status", Constants.POL_STATUS_02);
                            facadePayDao.updateFacadeTempPolicy(map);
                            logger.info("暂存单号:" + stagNo + "缴费全部成功");
                        }
                        return Result.success("缴费确认成功，生成保单号：" + polNo);
                    } else {
                        map = new HashMap<String, Object>();
                        map.put("appNo", appNo);
                        map.put("status", Constants.POL_STATUS_14);
                        facadePayDao.updateFacadeAppFormByAppno(map);
                        return Result.error(errinfo);
                    }
                } else {
                    logger.info("投保单号:" + appNo + "接受xml文件发送错误");
                    // 缴费接受后更新交易记录表信息
                    translog = new FacadeTransLog();
                    translog.setTransNo(serialnnumber);
                    translog.setResponseXml("");
                    translog.setResponseDate(new Date());
                    translog.setResultCode("-1");
                    translog.setResultDesc("返回报文为空");
                    facadePayDao.updateFacadeTransLog(translog);

                    return Result.error("缴费确认连接失败");
                }

            } else {
                return Result.error("投保单号" + appNo + "不满足条件,请刷新页面");
            }
        } catch (Exception e) {
            logger.info(e);
            return Result.error("缴费确认失败");
        }
    }

    private FacadePayment getFacadePaymentByPayId(String payId)
            throws Exception {

        return (FacadePayment) facadePayDao.query("getFacadePaymentByPayId",
                payId);
    }

    /**
     * 
     * @param paymentType
     * @return
     */
    private String getPayMode(String paymentType) {
        String payMode = paymentType;
        /*
         * 支付平台                 新意健险传值
            11  中国银联无卡支付            019
            1   中国银联网关支付            019
            12  上海银联（上海车险）      019
            13  非上海银联               019 
            7   微信                      016
            4   财付通（已停用）            报错
            5   支付宝                 017
            3   快钱支付                    018
            6   快钱支付WAP             018
            110 招商聚合                    110
            111 中信聚合-------111
            112 通联代扣-------112
         */
        if (Constants.WX_BIll99.equals(paymentType)
                || Constants.WX_BIll99WAP.equals(paymentType)) {
            payMode = Constants.PAYMODE_TYPE_018;//快钱支付,快钱支付WAP
        } else if (Constants.WX_ALIPAY.equals(paymentType)) {
            payMode = Constants.PAYMODE_TYPE_017;//支付宝
        } else if (Constants.WX_WECHAT.equals(paymentType)) {
            payMode = Constants.PAYMODE_TYPE_016;//微信
        } else if (Constants.WX_CHINAPAY.equals(paymentType)
                || Constants.WX_CHINANCPAY.equals(paymentType)
                || Constants.WX_SHYL.equals(paymentType)
                || Constants.WX_FSHYL.equals(paymentType)) {
            payMode = Constants.PAYMODE_TYPE_019;//银联无卡支付
        }
        return payMode;
    }
    
    /**
     * 对接新支付平台 只有3、7、13方式需要转换 helina 201903
     * @param payType
     * @return
     */
    private String getNewPayMode(String payType) {
        String payMode = payType;
        /*
         * 支付平台                 新意健险传值
            11  中国银联无卡支付            019
            1   中国银联网关支付            019
            12  上海银联（上海车险）      019
            13  非上海银联               019 
            7   微信                      016
            4   财付通（已停用）            报错
            5   支付宝                 017
            3   快钱支付                    018
            6   快钱支付WAP             018
            110 招商聚合                    110
            111 中信聚合-------111
            112 通联代扣-------112
         */
        if (Constants.WX_BIll99.equals(payType)) {
            payMode = Constants.PAYMODE_TYPE_018;//3快钱支付
        } else if (Constants.WX_WECHAT.equals(payType)) {
            payMode = Constants.PAYMODE_TYPE_016;//7微信
        } else if (Constants.WX_FSHYL.equals(payType)) {
            payMode = Constants.PAYMODE_TYPE_019;//13银联无卡支付
        }
        return payMode;
    }
    
    
    
    /**
     * 支付前较验(生效日期10分钟内 不能支付)
     * 
     * @param tp
     * @throws Exception
     */
    @Override
    public void validateBeforePay(FacadeTempPolicy tp) throws AppException,
            Exception {
        String stagNo = tp.getStagNo();
        List<FacadeAppForm> appFormlists = facadeAppFormService
                .getFacadeAppForm(stagNo);
        if (appFormlists == null || appFormlists.size() == 0) {
            throw new AppException("暂存单号[" + stagNo + "]下没有对应的投保单");
        }

        String effDate;
        for (FacadeAppForm facadeAppForm : appFormlists) {
            effDate = DateUtil.format(facadeAppForm.getEffDate(), "yyyy-MM-dd")
                    + " " + facadeAppForm.getEffHours() + ":00:00";
            if (!validatePayEffDate(DateUtil.parse(effDate,
                    "yyyy-MM-dd HH:mm:ss"))) {
                throw new AppException("暂存单号[" + stagNo + "]中投保单号["
                        + facadeAppForm.getAppNo() + "]支付时间不正确");
            }
        }
    }

    /**
     * 生效日期10分钟内 不能支付
     * 
     * @param effDate
     * @return
     */
    private boolean validatePayEffDate(Date effDate) {
        long tenMinTime = 600000;
        long effTime = effDate.getTime();
        if (effTime - tenMinTime < System.currentTimeMillis()) {
            return false;
        }
        return true;
    }

    @Override
    public FacadePayment noPaymentRecord(FacadeTempPolicy tp, String userCode)
            throws Exception {
        FacadePayment payment = saveFacadePayment(tp, userCode);
        return payment;
    }
    
    @Override
    public FacadeNewPayment noNewPaymentRecord(FacadeTempPolicy tp, String userCode)
            throws Exception {
        FacadeNewPayment newpayment = saveNewFacadePayment(tp, userCode);
        return newpayment;
    }
    
    /**
     * 根据暂存单号生成支付信息
     * 
     * @param tp
     * @param userCode
     * @return
     * @throws Exception
     */
    private FacadePayment saveFacadePayment(FacadeTempPolicy tp, String userCode)
            throws Exception {

        String stagNo = tp.getStagNo();
        String comCode = "";
        String prodType = tp.getProdType();
        if (Constants.PROD_TYPE_NLIFE.equals(prodType)) {
            FacadeAppForm facadeAppForm = facadeAppFormDao
                    .queryNLifeSingleFacadeAppFormByStagNo(stagNo);
            comCode = facadeAppForm.getDeptNo();
        }

        FacadePayment payment = new FacadePayment();
        payment.setTransNo(generatePaySerialNumber(tp.getStagNo()));
        payment.setTransDate(new Date());
        payment.setRequestCode(Config.getProp("nlife.pay.requestCode"));
        payment.setComCode(comCode);
        payment.setPayId(stagNo);
        payment.setTransAmt(DecimalUtil.round(tp.getAmount(), 2));
        payment.setInsertDate(new Date());
        payment.setStatus("1");
        payment.setPayName("暂存单号_" + stagNo);
        payment.setRemark("");
        payment.setFkChannelCode(tp.getPartnerNo());
        payment.setUserCode(userCode);
        facadePayDao.saveFacadePayment(payment);
        return payment;
    }
    
    /**
     * 根据暂存单号生成支付信息  对接新支付平台 何丽娜 20190314
     * 
     * @param tp
     * @param userCode
     * @return
     * @throws Exception
     */
    private FacadeNewPayment saveNewFacadePayment(FacadeTempPolicy tp, String userCode)
            throws Exception {

        String stagNo = tp.getStagNo();
        String comCode = "";
        String prodType = tp.getProdType();
        FacadeAppForm facadeAppForm = new FacadeAppForm();
        if (Constants.PROD_TYPE_NLIFE.equals(prodType)) {
            facadeAppForm = facadeAppFormDao
                    .queryNLifeSingleFacadeAppFormByStagNo(stagNo);
            comCode = facadeAppForm.getDeptNo();
        }
        Date startDate = facadeAppForm.getEffDate();
        FacadeNewPayment newpayment = new FacadeNewPayment();
        Date date = new Date();
        //TODO 起保时间年月日时分秒-10分钟
        Date expireDate = new Date(startDate.getTime() - 600000);
        newpayment.setChannelCode("jhcard");
        newpayment.setPayId(stagNo);   //原来是commamtid
        newpayment.setTransTime(date);
        newpayment.setRdSeq(generatePaySerialNumber(stagNo));  //原来是commamtid
        newpayment.setPaymentCode("jhcard" + stagNo);   //原来是commamtid
        newpayment.setApplyEntity(comCode); //原来是gatewayuser.getUserComcode()
        newpayment.setAmount(DecimalUtil.round(tp.getAmount(), 2));
        newpayment.setTitle("jhkPay");
        newpayment.setExpireDate(expireDate); //原来是disabledate
        newpayment.setInsertDate(date);
        newpayment.setTransState("1");
        newpayment.setIsJhcard("1");
        facadeNewPaymentDao.saveFacadeNewPayment(newpayment);
        return newpayment;
    }

    /**
     * 根据暂存单号生成支付流水号
     * 
     * @param stagNo
     * @return
     */
    private String generatePaySerialNumber(String stagNo) throws Exception {
        String code = facadePayDao.findFacadePaymentBystagNo(stagNo);
        if (code == null || code.equals("")) {
            code = "0001";
        }
        return stagNo + "PAY" + code;
    }

    /**
     * 更新支付信息表，出单系统暂存单表，出单系统投保单表,发送缴费确认
     */
    @Override
    public boolean updateFacade(FacadePayment payment) throws Exception {
        // 根据支付结果来更新出单系统暂存单表和出单系统投保单表
        Map<String, Object> map;
        FacadeTempPolicy facadeTempPolicy = facadeTempPolicyService
                .getFacadeTempPolicy(payment.getPayId());
        if (!Constants.POL_STATUS_11.equals(facadeTempPolicy.getStatus())
                && !Constants.POL_STATUS_13
                        .equals(facadeTempPolicy.getStatus())) {
            return false;
        }

        String statusCode = "0000";

        // 更新支付信息表
        facadePayDao.updateFacadePayment(payment);
        if (statusCode.equals(payment.getPayResult())) {
            // 更改暂存单和投保单状态
            map = new HashMap<String, Object>();
            map.put("payId", payment.getPayId());
            map.put("status", Constants.POL_STATUS_12);

            facadePayDao.updateFacadeAppForm(map);
            map.put("transNo", payment.getTransNo());
            facadePayDao.updateFacadeTempPolicy(map);
            logger.info("支付成功，暂存单号：" + payment.getPayId() + "相关暂存单表、投保单表相关记录完成");
            return true;
        } else {
            map = new HashMap<String, Object>();
            map.put("payId", payment.getPayId());
            map.put("status", Constants.POL_STATUS_13);
            facadePayDao.updateFacadeAppForm(map);

            facadePayDao.updateFacadeTempPolicy(map);
            logger.info("支付失败，暂存单号：" + payment.getPayId() + "相关暂存单表、投保单表相关记录完成");
            return false;
        }
    }
    
    /**
     * 遍历所有保单向交易系统发送缴费确认请求
     * 
     * @param payment
     */
    @Override
    public Result updatePayCostCallBack(FacadePayment payment) throws Exception {
        String stagNo = payment.getPayId();
        FacadeTempPolicy tp = facadeTempPolicyService
                .getFacadeTempPolicy(stagNo);
        if (tp == null) {
            return Result.error("暂存单号[" + stagNo + "]无记录");
        }

        // 新意健险确认
        // 获取所有保单号
        List<FacadeAppForm> appForms = facadePayDao
                .findFacadeAppFormByAppno(stagNo);
        // 根据暂存单号获取暂存单信息
        FacadeTempPolicy facadeTempPolicy = facadeTempPolicyDao
                .queryFacadeTempPolicyById(payment.getPayId());
        Map<String, String> xmlMap = new HashMap<String, String>();
        Map<String, Object> map;
        FacadeTransLog translog;
        int sumNumber = 0; // 缴费确认成功次数
        //
        xmlMap.put("TRANSRDATE", DateUtil.format(payment.getFeedbackDate(),
                "yyyy-MM-dd HH:mm:ss"));
        xmlMap.put("TRANSRDATE",
                DateUtil.format(new Date(), "yyyy-MM-dd HH:mm:ss"));
        String cardNo = null;
        for (FacadeAppForm appForm : appForms) {
            try {
                logger.info("投保单号:" + appForm.getAppNo() + "开发发送缴费确认请求");
                //激活保单卡号取得
                cardNo = cardInfoDao.getCardNoByAppNo(appForm.getAppNo(), stagNo);
                xmlMap.put("APPNO", appForm.getTradAppNo());
                xmlMap.put("PRODUCTCODE", appForm.getInsuPlanNo());
                xmlMap.put("PARTNERCODE", facadeTempPolicy.getPartnerNo());
                xmlMap.put("PARTNERSUBCODE",
                        facadeTempPolicy.getPartnerSaleNo());
                // 根据投保单号生成交易流水号
                String serialnnumber = generateTradingSerialNumber(appForm
                        .getAppNo());
                xmlMap.put("SERIALNUMBER", serialnnumber);
                // xmlMap.put("USERCODE",tp.getOperator());

                xmlMap.put("ENDORSEAPPNO", "");// 批改列为空
                xmlMap.put("BUSITYPE", "T");
                xmlMap.put("PAYFEE", appForm.getTotPremamt() + "");
                xmlMap.put("PAYDATE", DateUtil.format(payment.getPayDate(),
                        "yyyy-MM-dd HH:mm:ss"));
                xmlMap.put("CUSTOMERNO", payment.getMerId());
                xmlMap.put("USERCODE", payment.getUserCode());
                String payMode = getPayMode(payment.getPaymentType());
                xmlMap.put("PAY_MODE", payMode);
                xmlMap.put("CARDNO", cardNo);

                String xml = FreeMarkerUtil.process(
                        Config.getProp("nlife.T03.templates"), xmlMap);
                logger.info("投保单号:" + appForm.getAppNo() + "生成FreeMarker为:"
                        + xml);
                // 缴费发送前插入交易记录表信息
                translog = new FacadeTransLog();
                translog.setTransNo(serialnnumber);
                translog.setTransCode(Constants.GW_CH_TX_T03);
                translog.setStagNo(payment.getPayId());
                translog.setAppNo(appForm.getAppNo());
                translog.setRequestXml(xml);
                translog.setRequestDate(new Date());
                facadePayDao.insertFacadeTransLog(translog);
                String responseXml = HttpConnectorUtil
                        .interaction(Config.getProp("nlife.trial.url"), xml,
                                facadeTempPolicy.getPartnerNo(),
                                Constants.GW_CH_TX_T03);
                if (StrUtil.isNotEmpty(responseXml)) {
                    logger.info("投保单号:" + appForm.getAppNo() + "返回缴费确认报文为：" + responseXml);
                    Document document = DocumentHelper.parseText(responseXml);
                    Element root = document.getRootElement();
                    String resultCode = root.selectSingleNode(
                            "/INSUREQRET/HEAD/RESULTCODE").getText();
                    String errinfo = root.selectSingleNode(
                            "/INSUREQRET/HEAD/ERRINFO").getText();
                    String polNo = root
                            .selectSingleNode("/INSUREQRET/MAIN/POLNO") != null ? root
                            .selectSingleNode("/INSUREQRET/MAIN/POLNO")
                            .getText() : "";
                    String eUrl = root
                            .selectSingleNode("/INSUREQRET/MAIN/EURL") != null ? root
                            .selectSingleNode("/INSUREQRET/MAIN/EURL")
                            .getText() : "";
                    // 缴费接受后更新交易记录表信息
                    translog = new FacadeTransLog();
                    translog.setTransNo(serialnnumber);
                    translog.setResponseXml(responseXml);
                    translog.setResponseDate(new Date());
                    translog.setResultCode(resultCode);
                    translog.setResultDesc(errinfo);
                    try {
                        facadePayDao.updateFacadeTransLog(translog);
                    } catch (Exception e) {
                        logger.info("记录日志：", e);
                    }
                    if ("00".equals(resultCode) || "02".equals(resultCode)) {
                        map = new HashMap<String, Object>();
                        map.put("appNo", appForm.getAppNo());
                        map.put("status", Constants.POL_STATUS_02);
                        map.put("polNo", polNo);
                        map.put("polSubDate", new Date());
                        map.put("updateTime", new Date());
                        if (StrUtil.isNotEmpty(eUrl)) {
                            map.put("eUrl", eUrl);
                        }
                        facadePayDao.updateFacadeAppFormByAppno(map);
                        // 卡单表状态更新为已激活
                        CardInfo cardInfo = new CardInfo();
                        cardInfo.setCardNo(cardNo);
                        //cardInfo.setStatus(Constants.ACTIR_CARD_ACTIVABLE);
                        cardInfo.setStagNo(stagNo);
                        //激活时间
                        cardInfo.setAppDate(DateUtil.getNowDate(
                                "yyyy-MM-dd HH:mm:ss"));
                        //起保时间
                        cardInfo.setEffDate(DateUtil.parse(appForm.getStringEffDate(),
                                "yyyy-MM-dd HH:mm:ss"));
                        cardInfoDao.updateCardStatus(cardInfo);
                        sumNumber++;
                    } else {
                        map = new HashMap<String, Object>();
                        map.put("appNo", appForm.getAppNo());
                        map.put("status", Constants.POL_STATUS_14);
                        facadePayDao.updateFacadeAppFormByAppno(map);
                    }
                } else {
                    logger.info("投保单号:" + appForm.getAppNo() + "接受xml文件发送错误");
                    // 缴费接收后更新交易记录表信息
                    translog = new FacadeTransLog();
                    translog.setTransNo(serialnnumber);
                    translog.setResponseXml("");
                    translog.setResponseDate(new Date());
                    translog.setResultCode("-1");
                    translog.setResultDesc("返回报文为空");
                    facadePayDao.updateFacadeTransLog(translog);
                }
                logger.info("投保单号:" + appForm.getAppNo() + "结束发送缴费确认请求");
            } catch (Exception e1) {
                logger.info(e1);
                return Result.error("缴费确认失败");
            }
        }
        // 当缴费确认全部成功，则更新暂存单表状态
        if (sumNumber == appForms.size()) {
            map = new HashMap<String, Object>();
            map.put("payId", payment.getPayId());
            map.put("status", Constants.POL_STATUS_02);
            facadePayDao.updateFacadeTempPolicy(map);
            logger.info("暂存单号:" + payment.getPayId() + "缴费全部成功");
        }else{
            return Result.error("缴费确认失败");
        }
        return Result.success("缴费确认成功");
    }
    
    /**
     * 遍历所有保单向交易系统发送缴费确认请求 
     * 
     * 对接新支付平台 20190312 helina
     * @param newPayment
     */
    @Override
    public Result updateNewPayCostCallBack(FacadeNewPayment newPayment) throws Exception {
        String stagNo = newPayment.getPayId();
        FacadeTempPolicy tp = facadeTempPolicyService
                .getFacadeTempPolicy(stagNo);
        if (tp == null) {
            return Result.error("暂存单号[" + stagNo + "]无记录");
        }

        // 新意健险确认
        // 获取所有保单号
        List<FacadeAppForm> appForms = facadePayDao
                .findFacadeAppFormByAppno(stagNo);
        // 根据暂存单号获取暂存单信息
        FacadeTempPolicy facadeTempPolicy = facadeTempPolicyDao
                .queryFacadeTempPolicyById(newPayment.getPayId());
        Map<String, String> xmlMap = new HashMap<String, String>();
        Map<String, Object> map;
        FacadeTransLog translog;
        int sumNumber = 0; // 缴费确认成功次数
        xmlMap.put("TRANSRDATE", DateUtil.format(newPayment.getFeedBackDate(),
                "yyyy-MM-dd HH:mm:ss"));//老的为回调时间 feedbacktime
        xmlMap.put("TRANSRDATE",
                DateUtil.format(new Date(), "yyyy-MM-dd HH:mm:ss"));
        String cardNo = null;
        String pricelessType = null;
        for (FacadeAppForm appForm : appForms) {
            try {
                logger.info("投保单号:" + appForm.getAppNo() + "开发发送缴费确认请求");
                //cardNo = cardInfoDao.getCardNoByAppNo(appForm.getAppNo(), stagNo);
                //激活保单卡号取得及是否有价状态
                CardInfo cardInfoNP = cardInfoDao.getCardNoPriceByAppNo(appForm.getAppNo(), stagNo);
                cardNo = cardInfoNP.getCardNo();
                pricelessType = cardInfoNP.getPricelessType();
                xmlMap.put("APPNO", appForm.getTradAppNo());
                xmlMap.put("PRODUCTCODE", appForm.getInsuPlanNo());
                xmlMap.put("PARTNERCODE", facadeTempPolicy.getPartnerNo());
                xmlMap.put("PARTNERSUBCODE",
                        facadeTempPolicy.getPartnerSaleNo());
                // 根据投保单号生成交易流水号
                String serialnnumber = generateTradingSerialNumber(appForm
                        .getAppNo());
                xmlMap.put("SERIALNUMBER", serialnnumber);
                // xmlMap.put("USERCODE",tp.getOperator());

                xmlMap.put("ENDORSEAPPNO", "");// 批改列为空
                xmlMap.put("BUSITYPE", "T");
                xmlMap.put("PAYFEE", appForm.getTotPremamt() + "");
                xmlMap.put("PAYDATE", DateUtil.format(newPayment.getPayDate(),
                        "yyyy-MM-dd HH:mm:ss"));
                xmlMap.put("CUSTOMERNO", newPayment.getMerid());//老的为MerId
                xmlMap.put("USERCODE", newPayment.getUserCode());
                String payMode = getNewPayMode(newPayment.getPayType());//老的为paymentType 支付方式  xiegexinfangfa
                xmlMap.put("PAY_MODE", payMode);
                xmlMap.put("CARDNO", cardNo);
                if ("1".equals(pricelessType)) {
                	xmlMap.put("VERIFICATIONCODE", newPayment.getAbstracts());//新支付平台报文中须传对账码
                }

                String xml = FreeMarkerUtil.process(
                        Config.getProp("nlife.T03.templates"), xmlMap);
                logger.info("投保单号:" + appForm.getAppNo() + "生成FreeMarker为:"
                        + xml);
                // 缴费发送前插入交易记录表信息
                translog = new FacadeTransLog();
                translog.setTransNo(serialnnumber);
                translog.setTransCode(Constants.GW_CH_TX_T03);
                translog.setStagNo(newPayment.getPayId());
                translog.setAppNo(appForm.getAppNo());
                translog.setRequestXml(xml);
                translog.setRequestDate(new Date());
                facadePayDao.insertFacadeTransLog(translog);
                String responseXml = HttpConnectorUtil
                        .interaction(Config.getProp("nlife.trial.url"), xml,
                                facadeTempPolicy.getPartnerNo(),
                                Constants.GW_CH_TX_T03);
                if (StrUtil.isNotEmpty(responseXml)) {
                    logger.info("投保单号:" + appForm.getAppNo() + "返回缴费确认报文为：" + responseXml);
                    Document document = DocumentHelper.parseText(responseXml);
                    Element root = document.getRootElement();
                    String resultCode = root.selectSingleNode(
                            "/INSUREQRET/HEAD/RESULTCODE").getText();
                    String errinfo = root.selectSingleNode(
                            "/INSUREQRET/HEAD/ERRINFO").getText();
                    String polNo = root
                            .selectSingleNode("/INSUREQRET/MAIN/POLNO") != null ? root
                            .selectSingleNode("/INSUREQRET/MAIN/POLNO")
                            .getText() : "";
                    String eUrl = root
                            .selectSingleNode("/INSUREQRET/MAIN/EURL") != null ? root
                            .selectSingleNode("/INSUREQRET/MAIN/EURL")
                            .getText() : "";
                    // 缴费接受后更新交易记录表信息
                    translog = new FacadeTransLog();
                    translog.setTransNo(serialnnumber);
                    translog.setResponseXml(responseXml);
                    translog.setResponseDate(new Date());
                    translog.setResultCode(resultCode);
                    translog.setResultDesc(errinfo);
                    try {
                        facadePayDao.updateFacadeTransLog(translog);
                    } catch (Exception e) {
                        logger.info("记录日志：", e);
                    }
                    if ("00".equals(resultCode) || "02".equals(resultCode)) {
                        map = new HashMap<String, Object>();
                        map.put("appNo", appForm.getAppNo());
                        map.put("status", Constants.POL_STATUS_02);
                        map.put("polNo", polNo);
                        map.put("polSubDate", new Date());
                        map.put("updateTime", new Date());
                        if (StrUtil.isNotEmpty(eUrl)) {
                            map.put("eUrl", eUrl);
                        }
                        facadePayDao.updateFacadeAppFormByAppno(map);
                        // 卡单表状态更新为已激活
                        CardInfo cardInfo = new CardInfo();
                        cardInfo.setCardNo(cardNo);
                        cardInfo.setStatus(Constants.ACTIR_CARD_ACTIVABLE);
                        cardInfo.setStagNo(stagNo);
                        //激活时间
                        cardInfo.setAppDate(DateUtil.getNowDate(
                                "yyyy-MM-dd HH:mm:ss"));
                        //起保时间
                        cardInfo.setEffDate(DateUtil.parse(appForm.getStringEffDate(),
                                "yyyy-MM-dd HH:mm:ss"));
                        cardInfoDao.updateCardStatus(cardInfo);
                        sumNumber++;
                    } else {
                        map = new HashMap<String, Object>();
                        map.put("appNo", appForm.getAppNo());
                        map.put("status", Constants.POL_STATUS_14);
                        facadePayDao.updateFacadeAppFormByAppno(map);
                    }
                } else {
                    logger.info("投保单号:" + appForm.getAppNo() + "接受xml文件发送错误");
                    // 缴费接收后更新交易记录表信息
                    translog = new FacadeTransLog();
                    translog.setTransNo(serialnnumber);
                    translog.setResponseXml("");
                    translog.setResponseDate(new Date());
                    translog.setResultCode("-1");
                    translog.setResultDesc("返回报文为空");
                    facadePayDao.updateFacadeTransLog(translog);
                }
                logger.info("投保单号:" + appForm.getAppNo() + "结束发送缴费确认请求");
            } catch (Exception e1) {
                logger.info(e1);
                return Result.error("缴费确认失败");
            }
        }
        // 当缴费确认全部成功，则更新暂存单表状态
        if (sumNumber == appForms.size()) {
            map = new HashMap<String, Object>();
            map.put("payId", newPayment.getPayId());
            map.put("status", Constants.POL_STATUS_02);
            facadePayDao.updateFacadeTempPolicy(map);
            logger.info("暂存单号:" + newPayment.getPayId() + "缴费全部成功");
        }else{
            return Result.error("缴费确认失败");
        }
        return Result.success("缴费确认成功");
    }

    /**
     * 新支付流程 4.未支付状态
     *
     * @param facadepayment
     * @return
     * @throws Exception
     */
    @Override
    public FacadePayment noPaymentStatus(FacadePayment facadepayment) throws Exception {
        facadepayment.setStatus("4");// 查询前将支付状态改为处理中
        facadePayDao.updateFacadePayment(facadepayment);
        // 调用支付查询接口
        long time1 = System.currentTimeMillis();
        Map<String, String> map = new HashMap<String, String>();
        map.put("SERIALNUMBER", facadepayment.getTransNo());
        map.put("PAYID", facadepayment.getPayId());
        map.put("USER_NAME", Config.getProp("nlife.webservice.user_name"));
        map.put("USER_PSW", Config.getProp("nlife.webservice.user_psw"));
        // 获取合作验证码
        String verificationCode = GatewayCache
                .getCache(Constants.FACADE_PAYMENT_KEY);
        String SIGN = MD5Util.md5One(
                facadepayment.getPayId() + "0001" + verificationCode)
                .toLowerCase();
        map.put("SIGN", SIGN);// 写规则
        String templates = Config.getProp("pay.P003.templates");
        String requestXml = FreeMarkerUtil.process(templates, map);
        try {
            logger.info("支付查询请求网销报文：" + requestXml);
            String responseXml = "";
            try {
                responseXml = PaymentClient.getRequest(requestXml);
            } catch (Exception e) {
                facadepayment.setStatus("1");// 如果查询超时或出错将支付状态置为1未支付状态
                facadePayDao.updateFacadePayment(facadepayment);
                logger.info(e);
                throw new Exception("支付查询超时或失败" + e);
            }
            logger.info("请求网销查询完成执行时间:" + (System.currentTimeMillis() - time1));
            logger.info("查询网销返回报文：" + responseXml);
            Document document = DocumentHelper.parseText(responseXml);
            Element root = document.getRootElement();
            String RESULTCODE = selectSingleNodeByRoot(root,
                    "/PAYRET/MAIN/RESULTCODE");
            if ("0000".equals(RESULTCODE) || "0004".equals(RESULTCODE)) {// 如果支付成功或支付成功但回调失败
                String TRANSNO = selectSingleNodeByRoot(root,
                        "/PAYRET/MAIN/TRANSNO");
                String TRANSDATE = selectSingleNodeByRoot(root,
                        "/PAYRET/MAIN/TRANSDATE");
                String REQUESTCODE = selectSingleNodeByRoot(root,
                        "/PAYRET/MAIN/REQUESTCODE");
                String PAYID = selectSingleNodeByRoot(root,
                        "/PAYRET/MAIN/PAYID");
                String COMCODE = selectSingleNodeByRoot(root,
                        "/PAYRET/MAIN/COMCODE");
                String MERID = selectSingleNodeByRoot(root,
                        "/PAYRET/MAIN/MERID");
                String PAYNO = selectSingleNodeByRoot(root,
                        "/PAYRET/MAIN/PAYNO");
                String PAYMENTTYPE = selectSingleNodeByRoot(root,
                        "/PAYRET/MAIN/PAYMENTTYPE");
                String PAYDATE = selectSingleNodeByRoot(root,
                        "/PAYRET/MAIN/PAYDATE");
                String PAYAMT = selectSingleNodeByRoot(root,
                        "/PAYRET/MAIN/PAYAMT");
                String payRemark = selectSingleNodeByRoot(root,
                        "/PAYRET/MAIN/PAYREMARK");
                facadepayment.setTransNo(TRANSNO);
                facadepayment.setTransDate(DateUtil.parse(TRANSDATE,
                        "yyyy-MM-dd HH:mm:ss"));
                facadepayment.setRequestCode(REQUESTCODE);
                facadepayment.setComCode(COMCODE);
                facadepayment.setMerId(MERID);
                facadepayment.setPayNo(PAYNO);
                facadepayment.setPayId(PAYID);
                facadepayment.setPaymentType(PAYMENTTYPE);
                facadepayment.setPayDate(DateUtil.parse(PAYDATE,
                        "yyyy-MM-dd HH:mm:ss"));
                facadepayment.setTransAmt(new BigDecimal(PAYAMT));
                facadepayment.setPayResult(RESULTCODE);
                facadepayment.setPayRemark(payRemark);
                facadepayment.setFeedbackDate(new Date());
                facadepayment.setStatus("2");
                boolean backFalg = updateFacade(facadepayment);
                if (backFalg) {
                    // 当支付成功时候调用缴费功能
                    updatePayCostCallBack(facadepayment);
                }
            } else {
                facadepayment.setStatus("1");// 如果查询返回是未支付状态或支付失败状态,都要把支付表状态置为1未支付状态
                facadePayDao.updateFacadePayment(facadepayment);
            }
        } catch (Exception e) {
            facadepayment.setStatus("1");// 如果查询返回是未支付状态或支付失败状态,都要把支付表状态置为1未支付状态
            facadePayDao.updateFacadePayment(facadepayment);
            logger.info(e);
        }
        return facadepayment;
    }

    private String selectSingleNodeByRoot(Element root, String path) {
        Node node = root.selectSingleNode(path);
        if (node == null) {
            return "";
        } else {
            return node.getText();
        }
    }

    /**
     * 新支付流程 4.未支付状态  对接新支付平台 helina 20190314
     *
     * @param facadepayment
     * @return
     * @throws Exception
     */
    @Override
    public FacadeNewPayment noNewPaymentStatus(FacadeNewPayment facadeNewPayment) throws Exception {
    	facadeNewPayment.setTransState("4");// 查询前将支付状态改为处理中
        facadeNewPaymentDao.updateFacadeNewPay(facadeNewPayment);
        // 调用收款状态查询接口
        long time1 = System.currentTimeMillis();
        Map<String, String> map = new HashMap<String, String>();
        map.put("RdSeq", facadeNewPayment.getRdSeq());
        Date date = new Date();
        map.put("TransDate", DateUtil.format(date, "yyyyMMdd"));
        map.put("TransTime", DateUtil.format(date, "HHmmss"));
        map.put("TransSeq", DateUtil.format(date, "yyyyMMddHHmmsss"));
        map.put("S3Sign", "");
        String templates = Config.getProp("pay.QryRecState.templates");
        String requestXml = FreeMarkerUtil.process(templates, map);
        try {
            logger.info("收款状态查询报文：" + requestXml);
            String url = Config.getProp("card.newpay.qryRecState.url");
            String responseXml = "";
            responseXml = HttpConnectorNewpayUtil.interaction(url, requestXml);

            logger.info("请求收款状态查询完成执行时间:"
                    + (System.currentTimeMillis() - time1));
            logger.info("查询收款状态返回报文：" + responseXml);
            Document document = DocumentHelper.parseText(responseXml);
            Element root = document.getRootElement();
            String RtnCode = selectSingleNodeByRoot(root, "/ATS/PUB/RtnCode");
            // 如果查询成功
            if ("success".equals(RtnCode)) {
                String transState = selectSingleNodeByRoot(root,
                        "/ATS/OUT/TransState");
                // 如果返回2-已收款，更新支付表信息
                if ("2".equals(transState)) {
                    String rdSeq = selectSingleNodeByRoot(root,
                            "/ATS/OUT/RdSeq");
                    String cancelState = selectSingleNodeByRoot(root,
                            "/ATS/OUT/CancelState");
                    String corpAct = selectSingleNodeByRoot(root,
                            "/ATS/OUT/CorpAct");
                    String recChannel = selectSingleNodeByRoot(root,
                            "/ATS/OUT/RecChannel");
                    String abstracts = selectSingleNodeByRoot(root,
                            "/ATS/OUT/Abstract");
                    String payMadeDate = selectSingleNodeByRoot(root,
                            "/ATS/OUT/PayMadeDate");
                    SimpleDateFormat sf = new SimpleDateFormat(
                            "yyyy-MM-dd HH:mm:ss");
                    Date parse = sf.parse(payMadeDate);
                    facadeNewPayment.setRdSeq(rdSeq);
                    facadeNewPayment.setCancelState(cancelState);
                    facadeNewPayment.setTransState(transState);
                    facadeNewPayment.setMerid(corpAct);
                    facadeNewPayment.setPayDate(parse);
                    facadeNewPayment.setAbstracts(abstracts);
                    facadeNewPayment.setFeedBackDate(new Date());
                    facadeNewPayment.setPayType(recChannel);
                    facadeNewPaymentDao.updateFacadeNewPay(facadeNewPayment);
                } else {// 如果查询返回是2-已收款以外状态继续调用支付接口
                    facadeNewPayment.setTransState("1");
                    facadeNewPaymentDao.updateFacadeNewPay(facadeNewPayment);
                }
            } else {
                //如果交易返回码是notexists，需换一个订单号请求
                if ("notexists".equals(RtnCode)) {
                    facadeNewPayment.setRdSeq(generatePaySerialNumber(
                            facadeNewPayment.getPayId()));
                }
                facadeNewPayment.setTransState("1");
                facadeNewPaymentDao.updateFacadeNewPay(facadeNewPayment);
            }
        } catch (Exception e) {
            facadeNewPayment.setTransState("1");// 如果查询返回是未支付状态或支付失败状态,都要把支付表状态置为1未支付状态
            facadeNewPaymentDao.updateFacadeNewPay(facadeNewPayment);
            logger.error("收款状态查询超时或失败:" + e);
        }
        return facadeNewPayment;
    }
    
    
    @Override
    public List<FacadeAppForm> alreadyPaymentStatus(String stagNo)
            throws Exception {
        return facadePayDao.findFacadeAppFormByAppno(stagNo);// 查询暂存单对应的所有保单
    }
    /**
     * 出库用
     * @param facadepayment
     * @return
     * @throws Exception
     */
    @Override
    public FacadePayment noPaymentStatusForOut(FacadePayment facadepayment) throws Exception {
         facadepayment.setStatus("4");//查询前将支付状态改为处理中
         facadePayDao.updateFacadePayment(facadepayment);
        //调用支付查询接口
         long time1=System.currentTimeMillis();
        Map<String,String> map=new HashMap<String,String>();
        map.put("SERIALNUMBER", facadepayment.getTransNo());
        map.put("PAYID", facadepayment.getPayId());
        map.put("USER_NAME", Config.getProp("nlife.webservice.user_name"));
        map.put("USER_PSW", Config.getProp("nlife.webservice.user_psw"));
        //获取合作验证码
        String verificationCode = GatewayCache.getCache(Constants.FACADE_PAYMENT_KEY);
        //其中 sign = md5(PAYID值+ REQUESTCODE值+key值)=md5(051283014901012A0001020001+“64位key值”)
        String SIGN = MD5Util.md5One(facadepayment.getPayId()+"0001"+verificationCode).toLowerCase();
        map.put("SIGN", SIGN);//写规则

        String templates = Config.getProp("pay.P003.templates");
        String requestXml = FreeMarkerUtil.process(templates, map);
        try {
            logger.info("支付查询请求网销报文：" + requestXml);
            String responseXml = "";
            try {
                responseXml = PaymentClient.getRequest(requestXml);
            } catch (Exception e) {
                facadepayment.setStatus("1");// 如果查询超时或出错将支付状态置为1未支付状态
                facadePayDao.updateFacadePayment(facadepayment);
                logger.info(e);
                throw new Exception("支付查询超时或失败" + e);
            }
            logger.info("请求支付平台查询完成执行时间:"+ (System.currentTimeMillis() - time1));
            logger.info("查询支付平台返回报文："+responseXml);
            Document document = DocumentHelper.parseText(responseXml);
            Element root =  document.getRootElement();
            String resultcode = selectSingleNodeByRoot(root,"/PAYRET/MAIN/RESULTCODE");
            if("0000".equals(resultcode) || "0004".equals(resultcode)){//如果查询为支付成功或者支付成功回调失败
                String TRANSNO = selectSingleNodeByRoot(root,"/PAYRET/MAIN/TRANSNO");
//                String TRANSDATE = selectSingleNodeByRoot(root,"/PAYRET/MAIN/TRANSDATE");
                String REQUESTCODE = selectSingleNodeByRoot(root,"/PAYRET/MAIN/REQUESTCODE");
                String PAYID = selectSingleNodeByRoot(root,"/PAYRET/MAIN/PAYID");
                String COMCODE = selectSingleNodeByRoot(root,"/PAYRET/MAIN/COMCODE");
                String MERID = selectSingleNodeByRoot(root,"/PAYRET/MAIN/MERID");
                String PAYNO = selectSingleNodeByRoot(root,"/PAYRET/MAIN/PAYNO");
                String PAYMENTTYPE = selectSingleNodeByRoot(root,"/PAYRET/MAIN/PAYMENTTYPE");
                String PAYDATE = selectSingleNodeByRoot(root,"/PAYRET/MAIN/PAYDATE");
                String PAYAMT = selectSingleNodeByRoot(root,"/PAYRET/MAIN/PAYAMT");
                String payRemark = selectSingleNodeByRoot(root,"/PAYRET/MAIN/PAYREMARK");
                facadepayment.setTransNo(TRANSNO);
                facadepayment.setRequestCode(REQUESTCODE);
                facadepayment.setComCode(COMCODE);
                facadepayment.setMerId(MERID);
                facadepayment.setPayNo(PAYNO);
                facadepayment.setPayId(PAYID);
                facadepayment.setPaymentType(PAYMENTTYPE);
                facadepayment.setPayDate(DateUtil.parse(PAYDATE,"yyyy-MM-dd HH:mm:ss"));
                facadepayment.setTransAmt(new  BigDecimal(PAYAMT));
                facadepayment.setPayResult(resultcode);
                facadepayment.setPayRemark(payRemark);
                facadepayment.setFeedbackDate(new Date());
                facadepayment.setStatus(Constants.PAYMENT_STATUS_2);
                //                   facadePayDao.updateFacadePayment(facadepayment);
             // 更新支付信息表
                facadePayDao.updateFacadePayment(facadepayment);
            }else{
                 facadepayment.setStatus("1");//如果查询返回是未支付状态或支付失败状态,都要把支付表状态置为1未支付状态
                 facadePayDao.updateFacadePayment(facadepayment);
                logger.info("查询支付系统支付ID："+facadepayment.getPayId()+"为未支付状态");
            }
        }catch (Exception e) {
             facadepayment.setStatus("1");//如果查询返回是未支付状态或支付失败状态,都要把支付表状态置为1未支付状态
             facadePayDao.updateFacadePayment(facadepayment);
            logger.info(e);
        }
         return facadepayment;
    }
    /**
     * 出库缴费完成更新出库表状态
     * @param payId
     * @param statusBef
     * @param statusAft
     * @throws Exception
     */
    @Override
    public void updatCommamtInfo(String payId,
            String statusBef, String statusAft) throws Exception {
        HashMap<String, Object> param = new HashMap<String, Object>();
        param.put("commamtId", payId);
        param.put("statusBef", statusBef);
        param.put("statusAft", statusAft);
        // 更新出库费用表的状态和预收单号
        commamtFeeDao.updatCommamtInfo(param);
    }

    /**
     * 出库缴费完成更新卡单表状态
     * @param payId
     * @param statusBef
     * @param statusAft
     * @throws Exception
     */
    @Override
    public void updateStatusByCommamtId(String payId, String statusBef,
            String statusAft) throws Exception {
        HashMap<String, Object> param = new HashMap<String, Object>();
        param.put("commamtId", payId);
        param.put("statusBef", statusBef);
        param.put("statusAft", statusAft);
        param.put("payMrk", "Y");
        outboundCardApplyDao.updateStatusByCommamtId(param);
    }
    
    /**
     * 根据出库ID查找出库人数字工号
     * @param payId
     * @return
     * @throws Exception
     */
    @Override
    public Map<String, String> getEmployeeNoByCommamtId(String payId) throws Exception {
        return (Map<String, String>)outboundCardApplyDao.getEmployeeNoByCommamtId(payId);
    }
    
    /**
     * 根据条件查询payment信息  helina 20190318 
     * @param map
     * @return
     * @throws Exception
     */
    @Override
    public FacadeNewPayment queryNewPayment(HashMap<String, String> map)
            throws Exception {
        return facadeNewPaymentDao.queryNewPayment(map);
    }
    
    /**
     * 更新收款表  helina 20190318 
     * 
     * @param facadeNewPayment
     * @throws Exception
     */
    @Override
    public boolean updateFacadeNewPay(FacadeNewPayment facadeNewPayment)
            throws Exception {
        return facadeNewPaymentDao.updateFacadeNewPay(facadeNewPayment);

    }
    
    /**
     * 根据投保单号再次发起缴费确 对接新支付平台 20190418 helina
     * 
     * @param cardNo
     * @param appNo
     * @param stagNo
     * @return
     * @throws Exception
     */
    @Override
    public Result newPaymentConfirmAgain(String cardNo, String appNo, String stagNo)
            throws Exception {
        FacadeTempPolicy facadeTempPolicy = facadeTempPolicyDao
                .queryFacadeTempPolicyById(stagNo);
        String templates = Constants.NLIFE_T03_TEMPLATES;
        String transCode = Constants.GW_CH_TX_T03;
        String trialUrl = Constants.NLIFE_TRIAL_URL;
        String resultCodeSuccess = Constants.NLIFE_STATUS_CODE;
        String resultCodeRepeat = "02";

        try {
            Map<String, Object> map = new HashMap<String, Object>();
            map.put("appNo", appNo);
            map.put("status", "'" + Constants.POL_STATUS_14 + "','"
                    + Constants.POL_STATUS_12 + "','"
                    + Constants.POL_STATUS_02 + "'");
            Map<String, Object> messageMap = facadeNewPaymentDao
                    .queryNewConfirmAgainMessage(map);
            Map<String, String> xmlMap = new HashMap<String, String>();
            FacadeTransLog translog;

            FacadeNewPayment facadeNewpayment = getFacadeNewPaymentByPayId(facadeTempPolicy
                    .getStagNo());
            FacadeAppForm appForm = facadeAppFormDao
                    .queryFacadeAppFormByAppNo(appNo);

            if (messageMap != null) {
                if (Constants.POL_STATUS_02.equals(messageMap.get("STATUS"))) {
                    return Result.success("您已出单成功");
                }
                String fkChannelCode = messageMap.get("FK_CHANNEL_CODE") != null ? messageMap
                        .get("FK_CHANNEL_CODE").toString() : "";
                String subChannelCode = messageMap.get("PARTNE_SALE_NO") != null ? messageMap
                        .get("PARTNE_SALE_NO").toString() : "";
                xmlMap.put("TRANSRDATE",
                        DateUtil.format(new Date(), "yyyy-MM-dd HH:mm:ss"));
                logger.info("投保单号:" + appNo + "开发发送缴费确认请求");
                xmlMap.put(
                        "APPNO",
                        messageMap.get("TRAD_APP_NO") != null ? messageMap.get(
                                "TRAD_APP_NO").toString() : "");
                xmlMap.put("PRODUCTCODE",
                        messageMap.get("INSU_PLAN_NO") != null ? messageMap
                                .get("INSU_PLAN_NO").toString() : "");
                xmlMap.put("PARTNERCODE", fkChannelCode);
                xmlMap.put("PARTNERSUBCODE", subChannelCode);
                String payMode = getNewPayMode(facadeNewpayment.getPayType());
                xmlMap.put("PAY_MODE", payMode);
                /*xmlMap.put(
                        "TH_MERCHANT",
                        messageMap.get("MER_ID") != null ? messageMap
                                .get("MER_ID") + "" : "");*/
                //xmlMap.put("PAY_NO", "");
                //xmlMap.put("PAY_NAME", "");
                //xmlMap.put("PAY_BUSINESS", "");

                // 根据投保单号生成交易流水号
                String serialnnumber = generateTradingSerialNumber(appNo);
                xmlMap.put("SERIALNUMBER", serialnnumber);

                xmlMap.put("ENDORSEAPPNO", "");// 批改列为空
                xmlMap.put("BUSITYPE", "T");
                FacadeNewPayment facadeNewPayment = getFacadeNewPaymentByPayId(stagNo);
                java.text.DecimalFormat myformat = new java.text.DecimalFormat(
                        "0.00");
                //激活卡一条缴费信息可能对应多条投保信息，金额是所有投保单金额总和
                String payfee = myformat
                      .format(appForm.getTotPremamt() == null ? "" : appForm.getTotPremamt());
                xmlMap.put("PAYFEE", payfee);
                xmlMap.put("PAYDATE", DateUtil.format(facadeNewPayment.getPayDate(),
                        "yyyy-MM-dd HH:mm:ss"));
                xmlMap.put("CUSTOMERNO", facadeNewPayment.getMerid());
                // 卡号
                xmlMap.put("CARDNO", cardNo);
                // 对账码
                xmlMap.put("VERIFICATIONCODE", facadeNewPayment.getAbstracts());
                String xml = FreeMarkerUtil.process(Config.getProp(templates),
                        xmlMap);
                logger.info("投保单号:" + appNo + "生成FreeMarker为:" + xml);
                // 缴费发送前插入交易记录表信息
                translog = new FacadeTransLog();
                translog.setTransNo(serialnnumber);
                translog.setTransCode(transCode);
                translog.setStagNo(stagNo);
                translog.setAppNo(appNo);
                translog.setRequestXml(xml);
                translog.setRequestDate(new Date());
                facadePayDao.insertFacadeTransLog(translog);
                String responseXml = HttpConnectorUtil
                        .interaction(Config.getProp(trialUrl), xml,
                                fkChannelCode, transCode);
                if (StrUtil.isNotEmpty(responseXml)) {// 这里是连接成功
                    logger.info(responseXml);
                    Document document = DocumentHelper.parseText(responseXml);
                    Element root = document.getRootElement();
                    String resultCode = root.selectSingleNode(
                            "/INSUREQRET/HEAD/RESULTCODE").getText();
                    String errinfo = root.selectSingleNode(
                            "/INSUREQRET/HEAD/ERRINFO").getText();
                    String polNo = root
                            .selectSingleNode("/INSUREQRET/MAIN/POLNO") != null ? root
                            .selectSingleNode("/INSUREQRET/MAIN/POLNO")
                            .getText() : "";
                    String eUrl = root
                            .selectSingleNode("/INSUREQRET/MAIN/EURL") != null ? root
                            .selectSingleNode("/INSUREQRET/MAIN/EURL")
                            .getText() : "";
                    // 缴费接受后更新交易记录表信息
                    translog = new FacadeTransLog();
                    translog.setTransNo(serialnnumber);
                    translog.setResponseXml(responseXml);
                    translog.setResponseDate(new Date());
                    translog.setResultCode(resultCode);
                    translog.setResultDesc(errinfo);
                    try {
                        facadePayDao.updateFacadeTransLog(translog);
                    } catch (Exception e) {
                        logger.info("记录日志：", e);
                    }
                    // 00缴费确认成功,02缴费重复投保
                    if (resultCodeSuccess.equals(resultCode)
                            || resultCodeRepeat.equals(resultCode)) {
                        map = new HashMap<String, Object>();
                        map.put("appNo", appNo);
                        map.put("status", Constants.POL_STATUS_02);
                        map.put("polNo", polNo);
                        map.put("polSubDate", new Date());
                        map.put("updateTime", new Date());
                        if (StrUtil.isNotEmpty(eUrl)) {
                            map.put("eUrl", eUrl);
                        }
                        facadePayDao.updateFacadeAppFormByAppno(map);

                        // 卡单表状态更新为已激活
                        CardInfo cardInfo = new CardInfo();
                        cardInfo.setCardNo(cardNo);
                        cardInfo.setStatus(Constants.ACTIR_CARD_ACTIVABLE);
                        //激活时间
                        cardInfo.setAppDate(DateUtil.getNowDate(
                                "yyyy-MM-dd HH:mm:ss"));
                        //起保时间
                        cardInfo.setEffDate(DateUtil.parse(appForm.getStringEffDate(),
                                "yyyy-MM-dd HH:mm:ss"));
                        cardInfoDao.updateCardStatus(cardInfo);
                        // 确认该保单号是否为最后一个缴费确认，如果是则修改暂存单表
                        map = new HashMap<String, Object>();
                        map.put("stagNo", stagNo);
                        map.put("status", Constants.POL_STATUS_02);
                        List<String> isExist = facadePayDao
                                .queryConfirmToLast(map);
                        if (isExist == null || isExist.size() == 0) {
                            map = new HashMap<String, Object>();
                            map.put("payId", stagNo);
                            map.put("status", Constants.POL_STATUS_02);
                            facadePayDao.updateFacadeTempPolicy(map);
                            logger.info("暂存单号:" + stagNo + "缴费全部成功");
                        }
                        return Result.success("缴费确认成功，生成保单号：" + polNo);
                    } else {
                        map = new HashMap<String, Object>();
                        map.put("appNo", appNo);
                        map.put("status", Constants.POL_STATUS_14);
                        facadePayDao.updateFacadeAppFormByAppno(map);
                        return Result.error(errinfo);
                    }
                } else {
                    logger.info("投保单号:" + appNo + "接受xml文件发送错误");
                    // 缴费接受后更新交易记录表信息
                    translog = new FacadeTransLog();
                    translog.setTransNo(serialnnumber);
                    translog.setResponseXml("");
                    translog.setResponseDate(new Date());
                    translog.setResultCode("-1");
                    translog.setResultDesc("返回报文为空");
                    facadePayDao.updateFacadeTransLog(translog);

                    return Result.error("缴费确认连接失败");
                }

            } else {
                return Result.error("投保单号" + appNo + "不满足条件,请刷新页面");
            }
        } catch (Exception e) {
            logger.info(e);
            return Result.error("缴费确认失败");
        }
    }
    
    private FacadeNewPayment getFacadeNewPaymentByPayId(String payId) throws Exception {
        return (FacadeNewPayment) facadeNewPaymentDao.query("getFacadeNewPaymentByPayId",payId);
    }


}
